using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Zhaoxi.Zhihu.Core.Common;

namespace Zhaoxi.Zhihu.Infrastructure.Interceptors;

public class DispatchDomainEventsInterceptor(IPublisher publisher):SaveChangesInterceptor
{
    public override int SavedChanges(SaveChangesCompletedEventData eventData, int result)
    {
        DispatchDomainEvents(eventData.Context).GetAwaiter().GetResult();
        return base.SavedChanges(eventData, result);
    }

    public override async ValueTask<int> SavedChangesAsync(SaveChangesCompletedEventData eventData, int result,
        CancellationToken cancellationToken = new CancellationToken())
    {
        await DispatchDomainEvents(eventData.Context);
        return await base.SavedChangesAsync(eventData, result, cancellationToken);
    }

    private async Task DispatchDomainEvents(DbContext? context)
    {
        if (context is null)return;

        var entities = context.ChangeTracker.Entries<BaseEntity>()
            .Where(e => e.Entity.DomainEvent.Any())
            .Select(e => e.Entity)
            .ToList();
        
        var domainEvents = entities.SelectMany(e => e.DomainEvent).ToList();
       
        entities.ForEach(e=>e.ClearDomainEvents());
        
        foreach (var domainEvent in domainEvents)
            await publisher.Publish(domainEvent);
    }
}